package game.cellmap;

import game.AbstractGame;
import game.GameListener;
import game.GraphicUtil;
import game.IImageRenderer;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;

public abstract class AbstractCellMapGame<TYPE extends AbstractCellMap<?>> extends AbstractGame implements IImageRenderer
{
    private TYPE  map;
    private Point mousePoint = null;
    
    protected enum MouseEventType
    {
        MOVED, DRAGGED
    }
    
    protected void fireMouseMotion(MouseEventType type, MouseEvent e)
    {
        if (isRunning())
        {
            mousePoint = getMap().convertMousePointToCoord(calcRelativeMousePoint(e.getPoint()));
        }
    }
    
    protected AbstractCellMapGame(boolean enableScrolling, TYPE map)
    {
        super(enableScrolling);
        this.map = map;
        GameListener.getInstance().addMouseMotionListener(new MouseMotionAdapter() {
            
            @Override
            public void mouseMoved(MouseEvent e)
            {
                fireMouseMotion(MouseEventType.MOVED, e);
            }
            
            @Override
            public void mouseDragged(MouseEvent e)
            {
                fireMouseMotion(MouseEventType.DRAGGED, e);
            }
        });
    }
    
    protected TYPE getMap()
    {
        return map;
    }
    
    protected Point getMousePoint()
    {
        return mousePoint;
    }
    
    protected Point getStartXY()
    {
        int startX = 0;
        int startY = 0;
        Dimension mapSize = getMap().getCellMapSize();
        if (mapSize.getWidth() < getFrameSize().getWidth())
        {
            startX = (getFrameSize().width - mapSize.width) / 2;
        }
        if (mapSize.getHeight() < getFrameSize().getHeight())
        {
            startY = (getFrameSize().height - mapSize.height) / 2;
        }
        return new Point(startX, startY);
    }
    
    protected Point calcRelativeMousePoint(Point point)
    {
        Point startXY = getStartXY();
        int x = point.x - startXY.x;
        int y = point.y - startXY.y;
        return new Point(x, y);
    }
    
    protected void drawCenteredImage(Graphics g, Image image)
    {
        Dimension mapSize = getMap().getCellMapSize();
        int endX = mapSize.width;
        int endY = mapSize.height;
        if (endX < getFrameSize().width)
        {
            endX = getFrameSize().width;
        }
        if (endY < getFrameSize().height)
        {
            endY = getFrameSize().height;
        }
        GraphicUtil.fillRect(g, new Point(0, 0), new Dimension(endX, endY), Color.BLACK);
        Point startXY = getStartXY();
        // Logger.log("STARTXY: " + startXY);
        g.drawImage(image, startXY.x, startXY.y, null);
    }
    
    @Override
    public abstract BufferedImage getImage();
    
    @Override
    public final void render(Graphics g)
    {
        GraphicUtil.clearScreen((Graphics2D) g, getFrameSize());
        if (isReset())
        {
            GraphicUtil.renderCenterText(g, "Status: " + getStatus() + "; Info: " + getInfo(), 30, getFrameSize());
        }
        else
        {
            BufferedImage image = getImage();
            if (image != null)
            {
                drawCenteredImage(g, image);
            }
        }
    }
}
